<template>
  <el-dialog :model-value="dialogVisible" @close="$emit('close')" title="批量新增" width="80%">
    <el-form-item label="资产类型:" prop="assetTypeName">
      <el-select
        v-model.trim="assetTypeName"
        class="w-full"
        popper-class="select-no-dropdown"
        placeholder="请选择资产类型"
        @click="showAssetSelect"
      />
    </el-form-item>
    <el-form-item>
      <el-button :disabled="form.list.length <= 1" @click="batchDelete">批量删除</el-button>
    </el-form-item>
    <el-form :model="form" ref="formRef">
      <el-table
        :data="form.list"
        style="width: 100%"
        @selection-change="handleSelect"
        :row-class-name="
          (row) => {
            row.row.index = row.rowIndex
          }
        "
        max-height="400"
      >
        <el-table-column type="selection" width="60px" />
        <el-table-column label="数据源名称" min-width="150px">
          <template #default="scope">
            <el-form-item
              :rules="[
                {
                  required: true,
                  validator: valideName,
                  trigger: 'blur'
                }
              ]"
              :prop="`list[${scope.$index}]name`"
            >
              <ns-input v-model="form.list[scope.$index].name" placeholder="请输入数据源名称" />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column label="归属机构" min-width="150px">
          <template #default="scope">
            <el-form-item
              :prop="`list[${scope.$index}]deptId`"
              :rules="[
                {
                  required: !form.list[scope.$index].deptId && !form.list[scope.$index].sysId,
                  message: '系统和机构至少填写一个',
                  trigger: 'change'
                }
              ]"
            >
              <el-cascader
                ref="deptCascader"
                v-model="form.list[scope.$index].deptId"
                placeholder="请选择归属机构"
                :props="cascaderProps"
                :options="deptList"
                filterable
                value-on-clear=""
                clearable
                :filter-method="sysFilterMethod"
                :rules="[
                  {
                    required: !form.list[scope.$index].deptId && !form.list[scope.$index].sysId,
                    message: '系统和机构至少填写一个',
                    trigger: 'change'
                  }
                ]"
              />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column label="归属系统" min-width="150px">
          <template #default="scope">
            <el-form-item :prop="`list[${scope.$index}]sysId`">
              <el-cascader
                ref="systemCascader"
                v-model="form.list[scope.$index].sysId"
                placeholder="请选择归属系统"
                :props="systemCascaderProps"
                :options="systemList"
                filterable
                value-on-clear=""
                :filter-method="sysFilterMethod"
                clearable
              />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column
          label="认证类型"
          min-width="150px"
          v-if="
            dynamicForm?.mainOption.show_name && assetTypeName != '' && formOption?.data?.authType
          "
        >
          <el-form-item prop="authType">
            <el-select
              v-model="formOption.data.authType"
              class="w-full"
              :placeholder="dynamicForm?.mainOption.show_name"
            >
              <el-option
                v-for="(item, index) in authTypeList"
                :key="'authType' + index"
                :label="item.show_val"
                :value="item.req_val"
              />
            </el-select>
          </el-form-item>
        </el-table-column>
        <template v-if="authType && option[authType].constructor === Object">
          <el-table-column min-width="150px" :label="`${option[authType].show_name}`">
            <template #default="scope">
              <el-form-item
                :prop="`list[${scope.$index}]${option[authType].req_name}`"
                :rules="
                  option[authType].is_required.includes(sqlName)
                    ? [
                        {
                          required: true,
                          message: option[authType].input_info,
                          trigger: 'blur'
                        }
                      ]
                    : []
                "
              >
                <ns-input
                  v-model="form.list[scope.$index][option[form.list[intact_prop]].req_name]"
                  :rows="3"
                  type="textarea"
                  :show-password="
                    option[form.list[scope.$index][intact_prop]].show_name == 'IP地址'
                  "
                  :placeholder="option[form.list[scope.$index][intact_prop]].input_info"
                />
              </el-form-item>
            </template>
          </el-table-column>
        </template>
        <template v-else-if="authType && option[authType].constructor === Array">
          <el-table-column
            v-for="item in option[authType]"
            :key="item.req_name"
            :label="`${item.show_name}`"
            min-width="150px"
          >
            <template #default="scope">
              <el-form-item
                :prop="`list[${scope.$index}]${item.req_name}`"
                :rules="
                  item.is_required.includes(sqlName)
                    ? [
                        {
                          required: true,
                          message: `${item.show_name}不能为空`,
                          trigger: item.input_type === 'input' ? 'blur' : 'change'
                        }
                      ]
                    : []
                "
              >
                <ns-input
                  v-if="true"
                  v-model="form.list[scope.$index][item.req_name]"
                  :placeholder="item.input_info"
                  :type="item.req_encrypt ? 'password' : 'text'"
                />
                <el-upload
                  v-else-if="item.input_type === 'file'"
                  v-model="form.list[scope.$index][item.req_name]"
                  :action="fileUploadOption.action"
                  :data="{ path: '/db/' + item.req_name }"
                  :drag="fileUploadOption.drag"
                  :multiple="fileUploadOption.multiple"
                  :limit="fileUploadOption.limit"
                  :headers="headers"
                  :on-exceed="handleExceed"
                  :on-success="(res) => handleUploadSuccess(res, item.req_name)"
                  :on-remove="(res) => handleUploadRemove(item.req_name)"
                  style="width: 80%"
                >
                  <el-button type="primary"   text bg  :icon="UploadFilled">点击上传</el-button>
                </el-upload>
              </el-form-item>
            </template>
          </el-table-column>
        </template>
        <el-table-column
          width="150px"
          label="操作"
          show-overflow-tooltip
          min-width="150px"
          fixed="right"
          v-if="
            dynamicForm?.mainOption.show_name && assetTypeName != '' && formOption?.data?.authType
          "
        >
          <template #default="scope">
            <el-button
              v-if="scope.$index == form.list.length - 1"
              :icon="Plus"
              size="small"
              circle
              class="ml-12px"
              @click="addRow('')"
            />

            <el-button
              v-if="form.list.length > 1"
              :icon="Minus"
              size="small"
              circle
              class="ml-12px"
              @click="delRow(scope.$index)"
            />
            <el-button
              size="small"
              link
              type="primary"
              class="ml-12px"
              @click="addRow(scope.$index)"
              >克隆</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <asset-select
      v-model="assetOption.show"
      v-if="assetOption.show"
      :type="source"
      @update-asset-type="updateAssetType"
    />
    <template #footer>
      <el-button type="primary" @click="submit">确定</el-button>
      <el-button @click="$emit('close')">取消</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import cloneDeep from 'lodash-es/cloneDeep'
import { UploadFilled, Remove, CirclePlus } from '@element-plus/icons-vue'
import { getAccessToken } from '@/utils/auth'
import { Plus, Minus, Close } from '@element-plus/icons-vue'
import { getConnectConfig } from '@/api/asset/taskManage/dataCollect'
import { SM4Decrypt } from '@/utils/sm4Util'
import { ElMessage } from 'element-plus'
import { handleTree } from '@/utils/tree'
import { SM4Encrypt } from '@/utils/sm4Util'
import { getSimpleDeptList } from '@/api/system/dept'
import { getSimpleSystemList } from '@/api/asset/taskManage'
import { createDataSource } from '@/api/dataSourceManage/index'
import assetSelect from './AssetSelect.vue'

const paramsChange = ref([])
const { proxy } = getCurrentInstance()
const props = defineProps({
  source: {
    type: String,
    default: ''
  },
  dialogVisible: {
    default: false,
    type: Boolean
  }
})
const sqlName = ref()
const assetOption = reactive({
  show: false
})
const rows = ref()
const keys = {}
const option = ref()
const activeAssetInfo = ref()
const assetTypeName = ref()
const emit = defineEmits('close')
const deptList = ref([])
const systemList = ref([])
const url = import.meta.env.VITE_UPLOAD_URL
const disabledArr = ref(['ip', 'port'])
const formRef = ref(null)
const visible = ref(false)
const intact_prop = ref()
const authType = ref()
const authTypeList = ref()
function showAssetSelect() {
  assetOption.show = true
}
const systemCascader = ref()
const deptCascader = ref()
const defaultPort = ref()
const dynamicForm = reactive({
  authTypeAppRelation: {},
  mainOption: {},
  specialSql: [],
  optionType: {}
})
const systemCascaderProps = reactive({
  checkStrictly: true,
  label: 'value',
  value: 'id',
  children: 'children',
  emitPath: false
})
const cascaderProps = reactive({
  checkStrictly: true,
  label: 'name',
  value: 'id',
  children: 'children',
  emitPath: false // 用于 cascader 组件：在选中节点改变时，是否返回由该节点所在的各级菜单的值所组成的数组，若设置 false，则只返回该节点的值
})
const headers = ref({ Authorization: 'Bearer ' + getAccessToken() })
const fileUploadOption = reactive({
  action: url,
  drag: false,
  multiple: false,
  limit: 1
})

let form = ref({
  list: [
    {
      connectType: 'params',
      advanceParams: {}
    }
  ]
})

let advanceGroup = ref([{ p_key: '', p_val: '' }])
const deleteAdvance = (index) => {
  if (advanceGroup.value.length > 1) {
    advanceGroup.value.splice(index, 1)
  }
}
const showAdvance = (index) => {
  form.value.list.visible.value = true
  paramsChange.value = cloneDeep(advanceGroup.value)
}
const cancle = () => {
  form.value.list.visible.value = false
  form.value.list.advanceGroup.value = cloneDeep(paramsChange.value)
}
const addAdvance = () => {
  if (advanceGroup.value.every((item) => item.p_key !== '' && item.p_val !== '')) {
    advanceGroup.value.push({ p_key: '', p_val: '' })
  } else {
    ElMessage.error('键名和值不能为空')
  }
}
const submitAdvance = () => {
  if (!advanceGroup.value.every((item) => item.p_key !== '' && item.p_val !== '')) {
    ElMessage.error('键名和值不能为空')
    return
  }
  const seen = new Map()
  for (const param of advanceGroup.value) {
    for (const [key, value] of Object.entries(param)) {
      if (key === 'p_key') {
        const keyValuePair = `${key}-${value}`
        if (seen.has(keyValuePair) && value != '') {
          ElMessage.error(`键名${value}重复`)
          return
        }
        seen.set(keyValuePair, true)
      }
    }
  }
  let arr = {}
  for (const k of advanceGroup.value) {
    arr[k.p_key] = k.p_val
  }
  form.value.list.advanceParams = arr
  visible.value = false
}
// 上传成功回调
function handleUploadSuccess(res, prop) {
  if (res.code === 200) {
    form.value.list[prop] = res.data.path
    formRef.value.validateField(prop)
  }
}
function handleUploadRemove(prop) {
  form.value.list[prop] = ''
  formRef.value.validateField(prop)
}
// 文件个数超出
function handleExceed() {
  proxy.$modal.msgError(`上传文件数量不能超过 ${fileUploadOption.limit} 个!`)
}
const formOption = reactive({ data: {} })
async function getDeptList() {
  const data = await getSimpleDeptList()
  deptList.value = data
}
async function getSystemList() {
  const data = await getSimpleSystemList()
  systemList.value = handleTree(data, 'id', 'pid')
}

function updateAssetType(sql) {
  assetTypeName.value = sql.name
  defaultPort.value = sql.defaultPort
  sqlName.value = sql.name
  activeAssetInfo.value = sql
  assetOption.show = false
  getAuthTypeList()
  formOption.data.authType = dynamicForm.authTypeAppRelation[assetTypeName.value][0].req_val
}
const valideName = (rules, value, callBack) => {
  if (!value) {
    return callBack(new Error('数据源名称不能为空'))
  }
  let index = 0
  form.value.list.forEach((item) => {
    item.name == value && index++
  })
  index >= 2 ? callBack(new Error('数据源名称不能重复')) : callBack()
}
const batchDelete = () => {
  form.value.list = form.value.list.filter((item) => {
    return !rows.value.includes(item)
  })
}
const handleSelect = (selectRows) => {
  rows.value = selectRows
}
const delRow = (index) => {
  form.value.list && form.value.list.length > 0 && form.value.list.splice(index, 1)
}
const addRow = (index) => {
  index === ''
    ? form.value.list.push(cloneDeep(keys))
    : form.value.list.push(cloneDeep(form.value.list[index]))
}
async function getConfig() {
  const data = await getConnectConfig()
  dynamicForm.authTypeAppRelation = data.interact_config?.authTypeAppRelation
  dynamicForm.mainOption = data.show_config.mainOption
  dynamicForm.specialSql = Object.keys(dynamicForm?.authTypeAppRelation)
  dynamicForm.optionType = data.show_config.optionType
  authTypeList.value = dynamicForm.mainOption.optionList
  getAuthTypeList()
}
function getAuthTypeList() {
  if (assetTypeName.value) {
    let flag = false
    for (const k in dynamicForm.specialSql) {
      const key = dynamicForm.specialSql[k]
      if (key.toLocaleLowerCase() == activeAssetInfo.value.name.toLocaleLowerCase()) {
        authTypeList.value = dynamicForm.authTypeAppRelation[key] || []
        flag = true
      }
    }
    if (!flag) {
      authTypeList.value = dynamicForm.mainOption.optionList || []
    }
    formOption.data[dynamicForm.mainOption.req_name] = authTypeList.value[0]?.req_val
  }

  if (formOption?.data.authType) {
    option.value = dynamicForm?.optionType[formOption?.data[dynamicForm.mainOption?.req_name]]

    for (let item in option.value?.params) {
      form.value.list[0][option.value?.params[item].req_name] = ''
      keys[option.value?.params[item].req_name] = ''
    }

    intact_prop.value = option.value?.connect_type?.req_name
    authType.value = form.value.list[0][intact_prop.value]
  }
}

async function processItems(rowData) {
  const promises = rowData.map((item) => {
    return createDataSource({
      ...item,
      datasourceType: props.source === 'dbSource' ? 1 : 2
    })
  })

  // 使用 Promise.all 等待所有异步操作完成，并获取它们的结果
  try {
    const results = await Promise.all(promises)
    // 在这里处理所有的结果
    return results
  } catch (error) {
    ElMessage.error(error)
  }
}
const submit = async () => {
  if (!assetTypeName.value) {
    ElMessage.error('请选择资产类型！')
    return
  }
  const data = await formRef.value.validate()

  if (!data) {
    console.log(data, 2)

    return
  }
  const rowData = form.value.list.map((item) => {
    return filterData(item)
  })
  for (const i in rowData) {
    for (const k in rowData[i].connectionInfo.params) {
      if (
        k.indexOf('password') > -1 ||
        k.indexOf('Password') > -1 ||
        k.indexOf('dbAccount') > -1 ||
        k.indexOf('userName') > -1
      )
        rowData[i].connectionInfo.params[k] &&
          (rowData[i].connectionInfo.params[k] = SM4Encrypt(rowData[i].connectionInfo.params[k]))
    }
  }
  const result = await processItems(rowData)
  if (result?.length == rowData?.length) {
    ElMessage.success('创建成功')
    emit('close', true)
  }
}

const filterData = (data) => {
  const { name, deptId, sysId, scanFilePath } = data
  let scanParam = {}
  let scanScopeParam = {}
  const deptCheckedNodes = deptCascader.value.getCheckedNodes()
  const systemCheckedNodes = systemCascader.value.getCheckedNodes()
  const params = Object.assign({}, data, {
    authType: formOption.data.authType,
    connectType: data.connectType
  })
  const rowData = {
    name: name,
    ip: data.ip || '',
    port: data.port || '',
    assetType: activeAssetInfo.value.name,
    assetTypeName: assetTypeName.value,
    dbName: data.default_db_name || '',
    deptId: deptId,
    sysId: sysId,
    department: deptCheckedNodes[0]?.pathLabels?.reverse().join(' / '),
    system: systemCheckedNodes[0]?.pathLabels?.reverse().join(' / '),
    ...scanParam,
    ...scanScopeParam,
    connectionInfo: {
      appType: activeAssetInfo.value.name,
      authType: formOption.data.authType,
      connectType: data.connectType,
      isDefault: 1,
      params: params
    }
  }
  return rowData
}
onMounted(() => {
  getSystemList()
  getDeptList()
  getConfig()
})
</script>
<style lang="scss" scoped>
.card {
  background-color: #ecf5ff;
  height: 25px;
  line-height: 25px;
  display: inline-block;
  color: #409eff;
  margin-left: 5px;
  font-size: 12px;
  border-width: 1px solid #d9ecff;
  border-radius: 4px;
  box-sizing: border-box;
  white-space: nowrap;
  padding: 0 10px;
}
</style>
